package com.ibm.cloud.banking.media.components;


import com.ibm.cloud.banking.constant.TransErrorMgt;
import com.ibm.cloud.banking.facade.account.dto.AccountInfoDTO;
import com.ibm.cloud.banking.facade.media.dto.MediaCardDTO;
import com.ibm.cloud.banking.media.entity.MediaCardAccountRel;
import com.ibm.cloud.banking.media.entity.MediaCardInfo;
import com.ibm.cloud.banking.media.repository.IMediaCardAccountRelMapper;
import com.ibm.cloud.banking.media.repository.IMediaCardInfoMapper;
import com.ibm.cloud.banking.platform.exception.BusinessException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

import io.micrometer.core.instrument.util.StringUtils;

@Component
public class MediaCardBasisComponent {

    static final Logger logger = LoggerFactory.getLogger(MediaCardBasisComponent.class);

    final static String CARD_STATUS_NORMAL = "2";
    final static String CARD_STATUS_NOT_ALLOCATE = "0";
    final static String CARD_STATUS_NOT_UPDATE_PASSWORD = "1";

    final static String MAIN_CARD_FLAG = "0";
    final static String SUB_CARD_FLAG = "1";

    @Autowired
    private IMediaCardInfoMapper mediaCardInfoMapper;

    @Autowired
    private IMediaCardAccountRelMapper mediaCardAccountRelMapper;

//    @Autowired
//    TellerQueryService teller;


    @Transactional
    public MediaCardDTO allocateMediaCard(MediaCardDTO mediaCardDTO) {

        MediaCardInfo cardInfo = this.getByCardNo(mediaCardDTO.getCardNo());

        if(!CARD_STATUS_NOT_ALLOCATE.equals(cardInfo.getStatus())){
            throw new BusinessException(TransErrorMgt.MEDIA_CARD_ALLOCATED.code,
                    TransErrorMgt.MEDIA_CARD_ALLOCATED.message);
        }

        if(!MAIN_CARD_FLAG.equals(cardInfo.getMainCardFlag())){
            throw new BusinessException(TransErrorMgt.MEDIA_NOT_MAIN_CARD.code,
                    TransErrorMgt.MEDIA_NOT_MAIN_CARD.message);
        }

        //TODO teller待处理
        //String branchId=teller.selectById(mediaCardDTO.getTransTellerId()).getBranchId();
        String branchId = "1";
        cardInfo.setCustomerNo(mediaCardDTO.getCustomerNo());
        // todo 暂未实现修改密码交易，为功能正常演示，卡状态直接修改为正常，跳过待修改密码过程
        cardInfo.setStatus(CARD_STATUS_NORMAL);
        //cardInfo.setStatus(CARD_STATUS_NOT_UPDATE_PASSWORD);
        cardInfo.setOpenDate(mediaCardDTO.getOpenDate());
        cardInfo.setTransTellerId(mediaCardDTO.getTransTellerId());
        cardInfo.setTransBranch(branchId);
        cardInfo.setPassword(mediaCardDTO.getPassword());
        cardInfo.setProductNo(mediaCardDTO.getProductNo());
        cardInfo.setLevel(mediaCardDTO.getLevel());

        //TODO 更新类型失败
        // 卡表不做分片处理，shardingId设置为null
        mediaCardInfoMapper.allocateMediaCard(cardInfo);
        this.saveCardAcctRel(mediaCardDTO);

        BeanUtils.copyProperties(cardInfo,mediaCardDTO);
        logger.info("客户编号：{}，卡号：{}分配成功。",mediaCardDTO.getCustomerNo(),
                cardInfo.getCardNo());
        return mediaCardDTO;
    }

    @Transactional
    public Integer saveCardAcctRel(MediaCardDTO mediaCardDTO){

        MediaCardAccountRel cardAcctRel = new MediaCardAccountRel();
        BeanUtils.copyProperties(mediaCardDTO,cardAcctRel);
        cardAcctRel.setCreateDt(new Date());

        return mediaCardAccountRelMapper.insert(cardAcctRel);

    }

    @Transactional
    public void initMediaCard(MediaCardInfo mediaCardInfo) {
        mediaCardInfoMapper.initCard(mediaCardInfo.getCardNo(),mediaCardInfo.getPassword());
    }


    public MediaCardDTO getMediaCardByCardNo(String cardNo) {

        MediaCardDTO mediaCardDTO = new MediaCardDTO();
        BeanUtils.copyProperties(this.getByCardNo(cardNo),mediaCardDTO);

        return mediaCardDTO;
    }

    /**
     * 根据卡号获取介质卡信息，如果卡绑定账号，同时获取账户类型及账号
     * @param cardNo 卡号
     * @return 介质卡信息
     */
    public MediaCardInfo getByCardNo(String cardNo) {

        MediaCardInfo mediaCardInfo = mediaCardInfoMapper.getMediaCardByCardNo(cardNo);

        if(mediaCardInfo==null){
            throw new BusinessException(TransErrorMgt.ENTITY_NOT_EXIST.code,
                    String.format(TransErrorMgt.ENTITY_NOT_EXIST.message,"卡介质"));
        }

        // 未分配的卡，卡与账号关系为null
        if(StringUtils.isNotEmpty(mediaCardInfo.getCustomerNo())){
            MediaCardAccountRel cardAccountRel = mediaCardAccountRelMapper.getCardAccountRelByCardNo(cardNo);
            if(cardAccountRel!=null){
                mediaCardInfo.setAccountNo(cardAccountRel.getAccountNo());
                mediaCardInfo.setType(cardAccountRel.getType());
            }
        }

        return mediaCardInfo;
    }

    @Transactional
    public void resetPasswordErrorTimes(String cardNo) {
        mediaCardInfoMapper.resetPasswordErrorTimes(cardNo);
    }

    @Transactional
    public void updatePasswordErrorTimes(String cardNo) {
        mediaCardInfoMapper.updatePasswordErrorTimes(cardNo);
    }

    @Transactional
    public void updateCardStatus(String cardNo, String preStatus, String nextStatus) {
        mediaCardInfoMapper.updateCardStatus(cardNo,preStatus,nextStatus);
    }

    public void allocateMediaCardRefund(MediaCardDTO mediaCardDTO) {
        MediaCardInfo cardInfo = this.getByCardNo(mediaCardDTO.getCardNo());
        cardInfo.setCustomerNo(null);
        cardInfo.setStatus("0");
        cardInfo.setStatus(null);
        cardInfo.setOpenDate(null);
        cardInfo.setTransTellerId(null);
        cardInfo.setTransBranch(null);
        cardInfo.setPassword(null);
        cardInfo.setProductNo(null);
        cardInfo.setLevel(null);
        mediaCardInfoMapper.updateByPrimaryKey(cardInfo);
        MediaCardAccountRel cardAccountRel = new MediaCardAccountRel();
        cardAccountRel.setCardNo(mediaCardDTO.getCardNo());
        cardAccountRel.setAccountNo(mediaCardDTO.getAccountNo());
        mediaCardAccountRelMapper.deleteCardAcctRel(mediaCardDTO.getCardNo(),mediaCardDTO.getAccountNo());
    }
}
